package com.dmwork.service.interaction.mq.sender;

import com.dmwork.service.interaction.mq.callback.ConfirmCallback;
import com.dmwork.service.interaction.mq.callback.ReturnCallback;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Component
public class MessageSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private ConfirmCallback confirmCallback;
    @Autowired
    private ReturnCallback returnCallback;

    // Comment
    @Value("${spring.rabbitmq.custom.sender.send-comment-message.exchange}")
    private String sendCommentMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-comment-message.routekey}")
    private String sendCommentMessageRoutekey;

    //Comment Like
    @Value("${spring.rabbitmq.custom.sender.send-comment-like-message.exchange}")
    private String sendCommentLikeMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-comment-like-message.routekey}")
    private String sendCommentLikeMessageRoutekey;

    //Feed
    @Value("${spring.rabbitmq.custom.sender.send-feed-message.exchange}")
    private String sendFeedMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-feed-message.routekey}")
    private String sendFeedMessageRouteKey;

    //Feed Read
    @Value("${spring.rabbitmq.custom.sender.send-feed-read-message.exchange}")
    private String sendFeedReadMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-feed-read-message.routekey}")
    private String sendFeedReadMessageRouteKey;

    //comment read
    @Value("${spring.rabbitmq.custom.sender.send-comment-read-message.exchange}")
    private String sendCommentReadMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-comment-read-message.routekey}")
    private String sendCommentReadMessageRoutekey;

    //comment like read
    @Value("${spring.rabbitmq.custom.sender.send-comment-like-read-message.exchange}")
    private String sendCommentLikeReadMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-comment-like-read-message.routekey}")
    private String sendCommentLikeReadMessageRoutekey;

    //batch file remove
    @Value("${spring.rabbitmq.custom.sender.send-batch-file-remove-message.exchange}")
    private String sendBatchFileRemoveMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-batch-file-remove-message.routekey}")
    private String sendBatchFileRemoveMessageRoutekey;

    //work collect count change
    @Value("${spring.rabbitmq.custom.sender.send-work-collect-count-change-message.exchange}")
    private String sendWorkCollectCountChangeMessageExchange;
    @Value("${spring.rabbitmq.custom.sender.send-work-collect-count-change-message.routekey}")
    private String sendWorkCollectCountChangeMessageRoutekey;

    /**
     * 向MQ发送评论消息，由消息服务消费并生成新的未读评论消息
     * @param customerId 消息通知的用户的id
     * @param commentId 评论id
     * @param type 评论消息所属类型：0->作品评论，1->动态评论
     * @param flag flag==1，添加消息；flag==0，删除消息
     */
    public void sendCommentMessage(String customerId, String commentId, Integer type, Integer flag) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("customerId", customerId);
        messageMap.put("commentId", commentId);
        messageMap.put("type", type);
        Map<String, Object> properties=new HashMap<>();
        properties.put("flag", flag);
        Message<Map<String, Object>> message = processRabbitTemplate(messageMap, properties, ConfirmCallback.COMMENT_CONFIRM, ReturnCallback.COMMENT_RETURN);
        rabbitTemplate.convertAndSend(sendCommentMessageExchange, sendCommentMessageRoutekey, message, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     *  向MQ发送点赞消息，由消息服务消费并生成新的未读点赞消息
     * @param customerId 消息通知的用户的id
     * @param likeId 点赞记录id
     * @param type 点赞消息所属类型：0->作品评论点赞，1->动态评论点赞
     * @param flag flag==1，添加消息；flag==0，删除消息
     */
    public void sendCommentLikeMessage(String customerId, String likeId, Integer type,Integer flag) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("customerId", customerId);
        messageMap.put("likeId", likeId);
        messageMap.put("type", type);
        HashMap<String, Object> properties = new HashMap<>();
        properties.put("flag", flag);
        Message<Map<String, Object>> message = processRabbitTemplate(messageMap, properties, ConfirmCallback.COMMENT_LIKE_CONFIRM, ReturnCallback.COMMENT_LIKE_RETURN);
        rabbitTemplate.convertAndSend(sendCommentLikeMessageExchange, sendCommentLikeMessageRoutekey, message, new CorrelationData(UUID.randomUUID().toString()));
    }


    /**
     * 向消息服务发送新动态发布的消息
     *
     * @param properties
     */
    public void sendFeedMessage(String customerId, String feedId, Map<String, Object> properties) {
        Map<String, Object> messageMap = new HashMap<>();
        messageMap.put("customerId", customerId);
        messageMap.put("feedId", feedId);
        Message<Map<String, Object>> msg = processRabbitTemplate(messageMap, properties, ConfirmCallback.FEED_CONFIRM, ReturnCallback.FEED_RETURN);
        rabbitTemplate.convertAndSend(sendFeedMessageExchange, sendFeedMessageRouteKey, msg, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     * 向消息服务发送当前用户新的已读动态的id列表
     *
     * @param customerId 用户id
     * @param properties 自定义属性
     */
    public void sendFeedReadMessage(String customerId, Map<String, Object> properties) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("customerId", customerId);
        Message<Map<String, Object>> message = processRabbitTemplate(messageMap, properties, ConfirmCallback.FEED_READ_CONFIRM, ReturnCallback.FEED_READ_RETURN);
        rabbitTemplate.convertAndSend(sendFeedReadMessageExchange, sendFeedReadMessageRouteKey, message, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     * 向消息服务发送用户id的消息，让消息服务将该用户的所有作品部分回复消息设置为已读
     *
     * @param customerId 用户id
     * @param properties 自定义属性
     */
    public void sendCommentReadMessage(String customerId, Map<String, Object> properties) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("customerId", customerId);
        Message<Map<String, Object>> message = processRabbitTemplate(messageMap, properties, ConfirmCallback.COMMENT_READ_CONFIRM, ReturnCallback.COMMENT_READ_RETURN);
        rabbitTemplate.convertAndSend(sendCommentReadMessageExchange, sendCommentReadMessageRoutekey, message, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     * 向消息服务发送用户id的消息，让消息服务将该用户的所有作品部分被点赞的通知消息设置为已读
     *
     * @param customerId 用户id
     * @param properties 自定义属性
     */
    public void sendCommentLikeReadMessage(String customerId, Map<String, Object> properties) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("customerId", customerId);
        Message<Map<String, Object>> message = processRabbitTemplate(messageMap, properties, ConfirmCallback.COMMENT_LIKE_READ_CONFIRM, ReturnCallback.COMMENT_LIKE_READ_RETURN);
        rabbitTemplate.convertAndSend(sendCommentLikeReadMessageExchange, sendCommentLikeReadMessageRoutekey, message, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     * 向oss模块投递包含要删除的多个文件url的信息，让oss去将该url对应的文件批量删除
     *
     * @param urlList    文件url列表
     * @param properties 自定义属性
     */
    public void sendBatchFileRemoveMessage(List<String> urlList, Map<String, Object> properties) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("urlList", urlList);
        Message<Map<String, Object>> message = processRabbitTemplate(messageMap, properties, ConfirmCallback.BATCH_FILE_REMOVE_CONFIRM, ReturnCallback.BATCH_FILE_REMOVE_RETURN);
        rabbitTemplate.convertAndSend(sendBatchFileRemoveMessageExchange, sendBatchFileRemoveMessageRoutekey, message, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     * 向MQ投递作品收藏数变化的信息，让作品模块更新指定作品的收藏数
     * @param workId 作品id
     * @param changeCount 作品收藏数变化值：1 -> 收藏数增加，-1 -> 收藏数减少
     * @param properties 自定义属性
     */
    public void sendWorkCollectCountChangeMessage(String workId, Integer changeCount, Map<String, Object> properties) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("workId", workId);
        messageMap.put("changeCount", changeCount);
        Message<Map<String, Object>> message = processRabbitTemplate(messageMap, properties, ConfirmCallback.WORK_COLLECT_COUNT_CHANGE_CONFIRM, ReturnCallback.WORK_COLLECT_COUNT_CHANGE_RETURN);
        rabbitTemplate.convertAndSend(sendWorkCollectCountChangeMessageExchange, sendWorkCollectCountChangeMessageRoutekey, message, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     * 向MQ投递作品收藏数变化的信息，让作品模块更新作品的收藏数
     * @param workCollectCountMap 每个作品id对应的该作品的收藏数
     * @param properties
     */
    public void sendWorkCollectCountChangeMessage(Map<String, Integer> workCollectCountMap ,Map<String, Object> properties) {
        Message<Map<String, Integer>> message = processRabbitTemplate(workCollectCountMap, properties, ConfirmCallback.WORK_COLLECT_COUNT_CHANGE_CONFIRM, ReturnCallback.WORK_COLLECT_COUNT_CHANGE_RETURN);
        rabbitTemplate.convertAndSend(sendWorkCollectCountChangeMessageExchange, sendWorkCollectCountChangeMessageRoutekey, message, new CorrelationData(UUID.randomUUID().toString()));
    }


    ///////////// 私有工具方法/////////////////

    /**
     * 处理并返回封装的消息对象，且分别设置确认机制和返回机制要调用的方法名
     * @param message 自定义消息对象
     * @param properties 自定义属性
     * @param confirmCallbackMethodName 消息确认回调方法名
     * @param returnCallbackMethodName 消息返回机制回调方法名
     * @param <T>
     * @return
     */
    private <T> Message<T> processRabbitTemplate(T message, Map<String, Object> properties, String confirmCallbackMethodName, String returnCallbackMethodName) {
        MessageHeaders headers = new MessageHeaders(properties);
        Message<T> msg = MessageBuilder.createMessage(message, headers);
        //分别设置确认机制和返回机制要调用的方法名
        confirmCallback.setCallbackName(confirmCallbackMethodName);
        returnCallback.setCallbackName(returnCallbackMethodName);

        rabbitTemplate.setConfirmCallback(confirmCallback.originalConfirmCallback);
        rabbitTemplate.setReturnCallback(returnCallback.originalReturnCallback);
        return msg;
    }

}
